﻿package Leophy.controls.MotionClip 
{
	import flash.display.MovieClip;
	import flash.events.Event;
	import flash.filters.BlurFilter;
	import flash.filters.DropShadowFilter;
	import flash.geom.ColorTransform;
	import flash.utils.Timer;
	import flash.utils.getTimer;
	import Tophy.utils.Debug;
	/**
	$(CBI)* ...
	$(CBI)* @author Tophy
	$(CBI)*/
	dynamic public class EasyMotionMovieClip extends MovieClip
	{
		private var _nowState:Object;
		private var _stateArray:Array;
		
		private var _motionning:Boolean = false;
		private var _isTimeMotionning:Boolean = false;
		
		public function get Motionning():Boolean {
			return _motionning;
		}
		
		private var _fromState:Object;
		private var _toState:Object;
		
		private var bl:BlurFilter;
		private var dp:DropShadowFilter;
		
		private var _nowT:Number;
		private var _motionStartTime:Date;
		private var _motionTotalT:Number;
		
		private var _motionFun:Function;
		
		public function EasyMotionMovieClip() 
		{
			super();
		//	this.filters = [bl, dp];
			recordState();
		}
		
		
		public function SetState(sObj:Object) {
			recordState();
			setMCstate(sObj);
		}
		public function GetState():Object {
			return getNowState();
		}
		public function  TimeMotionTo(sObj:Object,MotionType:Function,time_MS:uint=2000,delay:uint=0,fromObj:Object=null) {
			EndMotion();
			_isTimeMotionning = true;
			if (sObj.blurFilter != null) {
				setDefaultBlurFilter();
			}
			if (sObj.dropShadowFilter != null) {
				setDefaultDropShadowFilter();
			}
			if (fromObj != null) {
				if (fromObj.blurFilter != null ) {
					setDefaultBlurFilter();
				}
				if (fromObj.dropShadowFilter != null) {
					setDefaultDropShadowFilter();
				}
				SetState(fromObj);
			//	trace("Start fromObj.R:" + fromObj.R);
			}
			this.recordState();
			_motionFun = MotionType;
			_nowT = 0;
			_motionTotalT = time_MS;
			_motionStartTime = new Date()
			_motionStartTime.setMilliseconds(_motionStartTime.getMilliseconds()+delay);
			Set_ToStateObject(sObj);
			
			this.addEventListener(Event.ENTER_FRAME, timeMotionFun);
			_motionning = true;
		}
		public function  FrameMotionTo(sObj:Object,MotionType:Function,frames_NUM:uint=20,delay:uint=0,fromObj:Object=null) {
			EndMotion();
			_isTimeMotionning = false;
			if (sObj.blurFilter != null) {
				setDefaultBlurFilter();
			}
			if (sObj.dropShadowFilter != null) {
				setDefaultDropShadowFilter();
			}
			if (fromObj != null) {
				if (fromObj.blurFilter != null ) {
					setDefaultBlurFilter();
				}
				if (fromObj.dropShadowFilter != null) {
					setDefaultDropShadowFilter();
				}
				SetState(fromObj);
			}
			this.recordState();
			_motionFun = MotionType;
			_nowT = -delay;
			_motionTotalT = frames_NUM;
			_motionStartTime = new Date();
			Set_ToStateObject(sObj);
			
			this.addEventListener(Event.ENTER_FRAME, frameMotionFun);
			_motionning = true;
		}
		/**
		 * 停止动作
		 */
		public function EndMotion() {
			removeEvents();
			_fromState = null;
			_toState = null;
			_nowT = 0;
			_motionTotalT = 0;
			_motionning = false;
		}
		/**
		 * 更新当前动作进度
		 */
		public function UpdataMotion() {
			if (_motionning) {
				if (_isTimeMotionning) {
					timeMotionFun(null);
				}else {
					frameMotionFun(null);
				}
			}
		}
		////======================================================================
		
		private function setDefaultBlurFilter() {
			if(bl==null){
				bl = new BlurFilter(0, 0, 0);
			}
		}
		private function setDefaultDropShadowFilter() {
			if(dp==null){
				dp = new DropShadowFilter(0, 45, 0, 1, 0, 0, 0, 0);
			}
		}
		private function timeMotionFun(ev:Event) {
			_nowT = (new Date()).getTime() - this._motionStartTime.getTime();
			if (_nowT < 0) return;
			if (_nowT > _motionTotalT) {
				_nowT = _motionTotalT;
				motionFun();
				EndMotion();
				this.dispatchEvent(new MotionEvent(MotionEvent.MOTION_COMPLITE));
				return;
			}
			motionFun();
		}
		
		private function frameMotionFun(ev:Event) {
			_nowT++;
			if (_nowT < 0) return;
			if (_nowT > _motionTotalT) {
				EndMotion();
				this.dispatchEvent(new MotionEvent(MotionEvent.MOTION_COMPLITE));
				return;
			}
			
			motionFun();
			
		}
		private function removeEvents() {
			this.removeEventListener(Event.ENTER_FRAME, timeMotionFun);
			this.removeEventListener(Event.ENTER_FRAME, frameMotionFun);
		}
		private function Set_ToStateObject(sObj:Object) {
			this._fromState = this.getNowState();
			//trace("_fromState.R:"+_fromState.R)
			//Debug.traceObj(this._fromState);
			//Debug.traceObj(this._nowState);
			
			this._toState = new Object();
			
			if (sObj.x != null) {
				this._toState.x = sObj.x - this._fromState.x;
			}
			if (sObj.y != null) {
				this._toState.y = sObj.y - this._fromState.y;
			}
			
			if (sObj.width != null) {
				this._toState.width = sObj.width - this._fromState.width;
			}
			if (sObj.height != null) {
				this._toState.height = sObj.height - this._fromState.height;
			}
			
			if (sObj.scaleX != null) {
				this._toState.scaleX = sObj.scaleX - this._fromState.scaleX;
			}
			if (sObj.scaleY != null) {
				this._toState.scaleY = sObj.scaleY - this._fromState.scaleY;
			}
			if (sObj.alpha != null) {
				this._toState.alpha = sObj.alpha - this._fromState.alpha;
			}
			
			if (sObj.R != null) {
				this._toState.R = sObj.R - this._fromState.R;
			}
			if (sObj.G != null) {
				this._toState.G = sObj.G - this._fromState.G;
			}
			if (sObj.B != null) {
				this._toState.B = sObj.B - this._fromState.B;
			}
			
			if (sObj.blurFilter != null) {
				
				this._toState.blurFilter = new Object();
				this._toState.blurFilter.blurX = sObj.blurFilter.blurX - this._fromState.blurFilter.blurX;
				this._toState.blurFilter.blurY = sObj.blurFilter.blurY - this._fromState.blurFilter.blurY
				this._toState.blurFilter.quality = sObj.blurFilter.quality - this._fromState.blurFilter.quality;
				if (this._toState.blurFilter.blurX == 0 && this._toState.blurFilter.blurY == 0 && this._toState.blurFilter.quality == 0) {
					this._toState.blurFilter = null;
				}
			}
			
			if (sObj.dropShadowFilter != null) {
				
				this._toState.dropShadowFilter = new Object();
				this._toState.dropShadowFilter.distance = sObj.dropShadowFilter.distance - this._fromState.dropShadowFilter.distance;
				this._toState.dropShadowFilter.angle = sObj.dropShadowFilter.angle - this._fromState.dropShadowFilter.angle;
				this._toState.dropShadowFilter.color = sObj.dropShadowFilter.color - this._fromState.dropShadowFilter.color;
				this._toState.dropShadowFilter.alpha = sObj.dropShadowFilter.alpha - this._fromState.dropShadowFilter.alpha;
				this._toState.dropShadowFilter.blurX = sObj.dropShadowFilter.blurX - this._fromState.dropShadowFilter.blurX;
				this._toState.dropShadowFilter.blurY = sObj.dropShadowFilter.blurY - this._fromState.dropShadowFilter.blurY;
				this._toState.dropShadowFilter.strength = sObj.dropShadowFilter.strength - this._fromState.dropShadowFilter.strength;
				this._toState.dropShadowFilter.quality = sObj.dropShadowFilter.quality - this._fromState.dropShadowFilter.quality;
				var f:Boolean = false;
				for (var p in this._toState.dropShadowFilter) {
					if (this._toState.dropShadowFilter[p] != 0) {						
						f = true;
						break;
					}
				}
				if (!f) {
					this._toState.dropShadowFilter = null;
				}
			}
			//trace("Set_NowStage fromObj.R"+_fromState.R)
		}                                                        
		private function motionFun() { 
			var bl:Number = _motionFun(_nowT, 0, 1, _motionTotalT, null);
			//trace("time=", _nowT, _motionTotalT, bl,_fromState.R,_toState.R,"now=_from?",_nowState==_fromState);
			var nowObj:Object = new Object();
			
			if (_toState.x != null && _toState.x!=0) {
				nowObj.x = _fromState.x + _toState.x * bl;
				
			}
			if (_toState.y != null && _toState.y!=0) {
				nowObj.y = _fromState.y + _toState.y * bl;
			}
			
			if (_toState.width != null && _toState.width!=0) {
				nowObj.width = _fromState.width + _toState.width * bl;
			}
			if (_toState.height != null && _toState.height!=0) {
				nowObj.height = _fromState.height + _toState.height * bl;
			}
			
			if (_toState.scaleX != null && _toState.scaleX!=0) {
				nowObj.scaleX = _fromState.scaleX + _toState.scaleX * bl;
			}
			if (_toState.scaleY != null && _toState.scaleY!=0) {
				nowObj.scaleY = _fromState.scaleY + _toState.scaleY * bl;
			}
			if (_toState.alpha != null && _toState.alpha!=0) {
				nowObj.alpha = _fromState.alpha + _toState.alpha * bl;
			}
			
			if (_toState.R != null) {
				nowObj.R = _fromState.R + _toState.R * bl;
			}
			if (_toState.G != null) {
				nowObj.G = _fromState.G + _toState.G * bl;
			}
			if (_toState.B != null) {
				nowObj.B = _fromState.B + _toState.B * bl;
			}
			
			if (_toState.blurFilter != null) {

				var blurX = _fromState.blurFilter.blurX + _toState.blurFilter.blurX * bl;
				var blurY = _fromState.blurFilter.blurY + _toState.blurFilter.blurY * bl;
				var quality = _fromState.blurFilter.quality + _toState.blurFilter.quality * bl;
				
				this.bl = new BlurFilter(blurX, blurY, quality);
				nowObj.blurFilter = this.bl;
			}
			if (_toState.dropShadowFilter != null) {
				
				var distance = _fromState.dropShadowFilter.distance + _toState.dropShadowFilter.distance * bl;
				var angle = _fromState.dropShadowFilter.angle + _toState.dropShadowFilter.angle * bl;
				var color = _fromState.dropShadowFilter.color + _toState.dropShadowFilter.color * bl;
				var alpha = _fromState.dropShadowFilter.alpha + _toState.dropShadowFilter.alpha * bl;
				var blurX2 = _fromState.dropShadowFilter.blurX + _toState.dropShadowFilter.blurX * bl;
				var blurY2 = _fromState.dropShadowFilter.blurY + _toState.dropShadowFilter.blurY * bl;
				var strength = _fromState.dropShadowFilter.strength + _toState.dropShadowFilter.strength * bl;
				var quality2 = _fromState.dropShadowFilter.quality + _toState.dropShadowFilter.quality * bl;
				
				this.dp=new DropShadowFilter(distance, angle, color, alpha, blurX2, blurY2, strength, quality2);
				nowObj.dropShadowFilter = this.dp;
			}
			
			setMCstate(nowObj);
		}
		
		private function recordState() {
			_nowState = getNowState();
		}
		private function setMCstate(sObj:Object) {
			if (sObj.x != null) {
				this.x = sObj.x;
			}
			if (sObj.y != null) {
				this.y = sObj.y;
			}
			if (sObj.scaleX != null) {
				this.scaleX = sObj.scaleX;
			}
			if (sObj.scaleY != null) {
				this.scaleY = sObj.scaleY;
			}
			if (sObj.width != null) {
				this.width = sObj.width;
			}
			if (sObj.height != null) {
				this.height = sObj.height;
			}
			if (sObj.alpha != null) {
				this.alpha = sObj.alpha;
			}
			
			if (sObj.R != null) {
				_nowState.R = sObj.R;
			}
			if (sObj.G != null) {
				_nowState.G = sObj.G;
			}
			if (sObj.B != null) {
				_nowState.B = sObj.B;
			}
			
			this.transform.colorTransform = new ColorTransform(1, 1, 1, this.alpha, _nowState.R, _nowState.G, _nowState.B, 0);
			//trace(_nowState.R, _nowState.G, _nowState.B);
			
			if (sObj.blurFilter != null) {
				_nowState.blurFilter = sObj.blurFilter;
			}
			if (sObj.dropShadowFilter != null) {
				_nowState.dropShadowFilter = sObj.dropShadowFilter;
			}
			var f:Array = new Array();
			if (sObj.blurFilter != null) {
				f.push(sObj.blurFilter);
			}
			if (sObj.dropShadowFilter != null) {
				f.push(sObj.dropShadowFilter);
			}
			if (f.length > 0) {
				this.filters = f;
			}
			
			//trace("---1----",sObj.blurFilter, sObj.dropShadowFilter,"|"+this.filters+"|"+this._nowState.blurFilter,this._nowState.dropShadowFilter);
			recordState();
			//trace("---2----",sObj.blurFilter, sObj.dropShadowFilter,"|"+this.filters+"|"+this._nowState.blurFilter,this._nowState.dropShadowFilter);
		}
		private function getNowState():Object {
			var sObj:Object = new Object();
			sObj.x = this.x;
			sObj.y = this.y;
			sObj.width = this.width;
			sObj.height = this.height;
			sObj.scaleX = this.scaleX;
			sObj.scaleY = this.scaleY;
			sObj.R = this.transform.colorTransform.redOffset;
			sObj.G = this.transform.colorTransform.greenOffset;
			sObj.B = this.transform.colorTransform.blueOffset;
			sObj.alpha = this.transform.colorTransform.alphaMultiplier;
			sObj.blurFilter = this.bl;
			sObj.dropShadowFilter = this.dp;
			
		//	trace("getNowStage R:" + sObj.R);
			return sObj;
		}
	}
	
}